<?php

namespace Largezhou\Admin\Table;

use Closure;
use Largezhou\Admin\ContentBuilder;

class Column extends ContentBuilder
{
    protected $name;
    protected $label;

    /**
     * 原始数据
     *
     * @var mixed
     */
    protected $origin;

    /**
     * 关联关系名
     *
     * @var
     */
    protected $relation;

    /**
     * 关联要显示的字段
     *
     * @var
     */
    protected $relationColumn;

    protected $displayCallbacks;

    public function __construct($name, $label = '')
    {
        $this->name = $name;
        $this->label = $this->formatLabel($label);
    }

    public function name()
    {
        return $this->name;
    }

    protected function formatLabel($label)
    {
        $label = $label ?: ucfirst($this->name);

        return str_replace(['.', '_'], ' ', $label);
    }

    protected function variables()
    {
        return [
            'name'  => $this->name,
            'label' => $this->label,
        ];
    }

    /**
     * 设置该列的关联关系
     *
     * @param string      $relation
     * @param string|null $relationColumn
     *
     * @return $this
     */
    public function setRelation(string $relation, string $relationColumn = null)
    {
        $this->relation = $relation;
        $this->relationColumn = $relationColumn;

        return $this;
    }

    public function handleValue($data): array
    {
        foreach ($data as $index => &$row) {
            // 用array_get可以获取到嵌套的数据
            $this->origin = $value = array_get($row, $this->name);

            if ($this->hasDisplayCallbacks()) {
                $value = $this->callDisplayCallbacks($value, $row, $index);
            }

            // 再用这种方式把嵌套的数据设置到类似'parent.title' => $value上
            $row[$this->name] = $value;
        }

        return $data;
    }

    protected function callDisplayCallbacks($value, $row, $index)
    {
        foreach ($this->displayCallbacks as $callback) {
            $value = call_user_func($callback, $value, $row, $index);
        }

        return $value;
    }

    /**
     * 添加一个用来处理当前列数据的回调
     *
     * @param Closure $callback (当前列数据: $value, 当前行数据: $row, 当前行索引: $index)
     *
     * @return $this
     */
    public function display(Closure $callback)
    {
        $this->displayCallbacks[] = $callback;

        return $this;
    }

    protected function hasDisplayCallbacks(): bool
    {
        return !empty($this->displayCallbacks);
    }
}
